home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / prog / amisl090.zip / AMIS.MAC < prev    next >
Text File  |  1992-09-12  |  34KB  |  1,354 lines

  1. .XLIST
  2. ;-----------------------------------------------------------------------
  3. ; Alternate Multiplex Interrupt Specification Library
  4. ; AMIS.MAC    Public Domain 1992 Ralf Brown
  5. ;        You may do with this software whatever you want, but
  6. ;        common courtesy dictates that you not remove my name
  7. ;        from it.
  8. ;
  9. ; Version 0.90
  10. ; LastEdit: 9/12/92
  11. ;-----------------------------------------------------------------------
  12.  
  13. AMIS_VERSION equ 350    ;(version 3.5 of the Alternate Multiplex Interrupt Spec)
  14. AMISLIB_VERSION equ 090 ;(version 0.90 of this library)
  15.  
  16. ;-----------------------------------------------------------------------
  17. ; Return codes for various API calls
  18. ;
  19.  
  20. ; general, applies to all standard calls
  21. AMIS_NOTIMPLEMENTED      equ 0
  22. AMIS_SUCCESSFUL        equ 0FFh
  23.  
  24. ; additional return codes for Uninstall (function 02h)
  25. AMIS_UNINST_FAILED    equ 1
  26. AMIS_UNINST_WILL_DO    equ 2
  27. AMIS_UNINST_SAFE_ON    equ 3
  28. AMIS_UNINST_SAFE_OFF    equ 4
  29. AMIS_UNINST_TRYLATER     equ 5
  30.  
  31. ; additional return codes for Popup (function 03h)
  32. AMIS_POPUP_TRYLATER    equ 1
  33. AMIS_POPUP_WILLDO    equ 2
  34. AMIS_POPUP_BUSY        equ 3
  35. AMIS_POPUP_NEEDHELP    equ 4
  36.  
  37. ; additional return codes for Check Interrupt Chained (function 04h)
  38. AMIS_CHAIN_DONTKNOW    equ 1
  39. AMIS_CHAIN_HOOKED    equ 2
  40. AMIS_CHAIN_HOOKED_ADDR    equ 3
  41. AMIS_CHAIN_HOOKLIST    equ 4
  42. AMIS_CHAIN_NOTUSED    equ 0FFh
  43.  
  44. ; hotkey type bits returned by Get Hotkeys (function 05h)
  45. HK_INT09ENTRY        equ 1    ; TSR checks keys before calling orig INT 09h
  46. HK_INT09EXIT        equ 2    ; TSR checks keys after calling orig INT 09h
  47. HK_INT15ENTRY        equ 4    ; TSR checks keys before chaining INT 15h/AH=4Fh
  48. HK_INT15EXIT        equ 8    ; TSR checks keys after chaining INT 15h/AH=4Fh
  49. HK_INT16OLD        equ 10h ; TSR checks on INT 16/AH=00h-02h
  50. HK_INT16NEW        equ 20h ; TSR checks on INT 16/AH=10h-12h
  51.  
  52. ; hotkey shift bits returned by Get Hotkeys (function 05h)
  53. HK_NONE         equ 0000h  ; no shift keys
  54. HK_RSHIFT        equ 0001h  ; right shift key
  55. HK_LSHIFT        equ 0002h  ; left shift key
  56. HK_BOTHSHIFT        equ 0003h  ; both Shift keys must be pressed
  57. HK_ANYCTRL        equ 0004h  ; either Control key must be pressed
  58. HK_ANYALT        equ 0008h  ; either Alt key must be pressed
  59. HK_SCRLLOCK_ON        equ 0010h  ; ScrollLock must be on when hotkey pressed
  60. HK_NUMLOCK_ON        equ 0020h  ; NumLock must be on when hotkey pressed
  61. HK_CAPSLOCK_ON        equ 0040h  ; CapsLock must be on when hotkey pressed
  62. HK_ANYSHIFT        equ 0080h  ; either Shift key must be pressed
  63. HK_LCTRL        equ 0100h  ; left control key
  64. HK_LALT         equ 0200h  ; left Alt key
  65. HK_RCTRL        equ 0400h  ; right control key
  66. HK_RALT         equ 0800h  ; right Alt key
  67. HK_BOTHCTRL        equ 0500h  ; both Control keys must be pressed
  68. HK_BOTHALT        equ 0A00h  ; both Alt keys must be pressed
  69. HK_SCROLLOCK        equ 1000h  ; ScrollLock must be pressed with hotkey
  70. HK_NUMLOCK        equ 2000h  ; NumLock must be pressed with hotkey
  71. HK_CAPSLOCK        equ 4000h  ; CapsLock must be pressed with hotkey
  72. HK_SYSREQ        equ 8000h  ; SysRq must be pressed with hotkey
  73.  
  74. ; hotkey flag bits returned by Get Hotkeys (function 05h)
  75. HK_CHAINBEFORE        equ 1    ; TSR chains hotkey before processing it
  76. HK_CHAINAFTER        equ 2    ; TSR chains hotkey after processing it
  77. HK_MONITOR        equ 4    ; other TSRs should pass through this hotkey
  78.                 ; so that it can be monitored
  79. HK_NOPRESSRELEASE    equ 8    ; hotkey won't activate if other keys pressed
  80.                 ; and released before hotkey combination 
  81.                 ; completed
  82. HK_REMAPPED        equ 10h ; this key is remapped into some other key
  83.  
  84. HK_NOCHAIN        equ 0    ; TSR swallows hotkey
  85.  
  86. ; hotkey scan codes returned by Get Hotkeys (function 05h)
  87. SCAN_NONE    equ 0
  88. SCAN_ESC    equ 1
  89. SCAN_1        equ 2
  90. SCAN_2        equ 3
  91. SCAN_3        equ 4
  92. SCAN_4        equ 5
  93. SCAN_5        equ 6
  94. SCAN_6        equ 7
  95. SCAN_7        equ 8
  96. SCAN_8        equ 9
  97. SCAN_9        equ 10
  98. SCAN_0        equ 11
  99. SCAN_HYPHEN    equ 12
  100. SCAN_EQUAL    equ 13
  101. SCAN_BACKSP    equ 14
  102. SCAN_TAB    equ 15
  103. SCAN_Q        equ 16
  104. SCAN_W        equ 17
  105. SCAN_E        equ 18
  106. SCAN_R        equ 19
  107. SCAN_T        equ 20
  108. SCAN_Y        equ 21
  109. SCAN_U        equ 22
  110. SCAN_I        equ 23
  111. SCAN_O        equ 24
  112. SCAN_P        equ 25
  113. SCAN_LBRACKET    equ 26
  114. SCAN_RBRACKET    equ 27
  115. SCAN_ENTER    equ 28
  116. SCAN_CTRL    equ 29
  117. SCAN_A        equ 30
  118. SCAN_S        equ 31
  119. SCAN_D        equ 32
  120. SCAN_F        equ 33
  121. SCAN_G        equ 34
  122. SCAN_H        equ 35
  123. SCAN_J        equ 36
  124. SCAN_K        equ 37
  125. SCAN_L        equ 38
  126. SCAN_SEMICOLON    equ 39
  127. SCAN_SQUOTE    equ 40
  128. SCAN_BACKQUOTE    equ 41
  129. SCAN_LSHIFT    equ 42
  130. SCAN_BACKSLASH    equ 43
  131. SCAN_Z        equ 44
  132. SCAN_X        equ 45
  133. SCAN_C        equ 46
  134. SCAN_V        equ 47
  135. SCAN_B        equ 48
  136. SCAN_N        equ 49
  137. SCAN_M        equ 50
  138. SCAN_COMMA    equ 51
  139. SCAN_PERIOD    equ 52
  140. SCAN_SLASH    equ 53
  141. SCAN_RSHIFT    equ 54
  142. SCAN_GREYSTAR    equ 55
  143. SCAN_ALT    equ 56
  144. SCAN_SPACE    equ 57
  145. SCAN_CAPSLK    equ 58
  146. SCAN_F1        equ 59
  147. SCAN_F2        equ 60
  148. SCAN_F3        equ 61
  149. SCAN_F4        equ 62
  150. SCAN_F5        equ 63
  151. SCAN_F6        equ 64
  152. SCAN_F7        equ 65
  153. SCAN_F8        equ 66
  154. SCAN_F9        equ 67
  155. SCAN_F10    equ 68
  156. SCAN_NUMLK    equ 69
  157. SCAN_SCRLLK    equ 70
  158. SCAN_HOME    equ 71
  159. SCAN_UP        equ 72
  160. SCAN_PGUP    equ 73
  161. SCAN_GREYMINUS    equ 74
  162. SCAN_LEFT    equ 75
  163. SCAN_KP5    equ 76
  164. SCAN_RIGHT    equ 77
  165. SCAN_GREYPLUS    equ 78
  166. SCAN_END    equ 79
  167. SCAN_DOWN    equ 80
  168. SCAN_PGDN    equ 81
  169. SCAN_INS    equ 82
  170. SCAN_DEL    equ 83
  171. SCAN_SYSRQ    equ 84
  172. SCAN_F11    equ 87
  173. SCAN_F12    equ 88
  174. HK_ONRELEASE    equ 80h ; hotkey activates on key release (add to scan code)
  175.  
  176. ;-----------------------------------------------------------------------
  177. ; Return codes for AMISLIB functions
  178. ;
  179.  
  180. ; bit flags returned by CHECK_IF_HOTKEYS_USED
  181. HC_EXACT    equ 1        ; exact match found
  182. HC_SUPERSET    equ 2        ; some key whose shift states include ours used
  183. HC_SUBSET    equ 4        ; some key whose shift states included by one of ours used    
  184. HC_OVERLAP    equ 8        ; hotkey overlap found
  185. HC_MONITOR    equ 80h        ; other TSRs monitor one or more hotkeys, but no
  186.                 ;   actual conflict because caller chains them
  187.  
  188. HC_IS_CONFLICT  equ 7Fh        ; mask for testing whether conflict exists
  189.  
  190. ;-----------------------------------------------------------------------
  191. ;
  192. ; Set up a shorthand for the segment containing all the resident code and
  193. ; data.
  194. ; Note: the alignment must be PARA for the code to be properly relocatable
  195. ; in small-code memory models.
  196. ;
  197. TSRcode@ MACRO
  198. TGROUP GROUP RESIDENT_CODE
  199. RESIDENT_CODE SEGMENT PUBLIC PARA 'TSRCODE'
  200.     ASSUME    DS:NOTHING,ES:NOTHING,SS:NOTHING
  201.     ASSUME    CS:TGROUP
  202.     ENDM
  203. TSRcodeEnd@ MACRO
  204. RESIDENT_CODE ENDS
  205.     ENDM
  206.  
  207. ;-----------------------------------------------------------------------
  208. ;
  209. ; Set up shorthands for the segments containing all the resident data,
  210. ; initialized and uninitialized.
  211. ;
  212. TSRdata@ MACRO
  213. RESIDENT_DATA SEGMENT PUBLIC BYTE 'TSRCODE'
  214.     ENDM
  215. TSRdataEnd@ MACRO
  216. RESIDENT_DATA ENDS
  217.     ENDM
  218.  
  219. TSRbss@ MACRO
  220. RESIDENT_BSS SEGMENT PUBLIC BYTE 'TSRCODE'
  221.     ENDM
  222. TSRbssEnd@ MACRO
  223. RESIDENT_BSS ENDS
  224.     ENDM
  225.  
  226. ;-----------------------------------------------------------------------
  227. ;
  228. ; dummy segment for determining the size of the resident code in the
  229. ; executable
  230. ;
  231. TSRlast@ MACRO
  232. RESIDENT_END SEGMENT PUBLIC BYTE 'TSRCODE'
  233.     ENDM
  234. TSRlastEnd@ MACRO
  235. RESIDENT_END ENDS
  236.     ENDM
  237.  
  238. ;-----------------------------------------------------------------------
  239. ;
  240. ; Set up a shorthand for declaring all three resident segments and a group
  241. ; TGROUP for those segments.
  242. ;
  243. TSRgroup@ MACRO
  244. TSRcode@
  245. TSRcodeEnd@
  246. TSRdata@
  247. TSRdataEnd@
  248. TSRbss@
  249. TSRbssEnd@
  250. TSRlast@
  251. TSRlastEnd@
  252. TGROUP GROUP RESIDENT_CODE,RESIDENT_DATA,RESIDENT_BSS,RESIDENT_END
  253.     ENDM
  254.  
  255. ;-----------------------------------------------------------------------
  256. ;
  257. ; Some of the code in ALTMPX.ASM uses conditional assembly to handle
  258. ; segment registers differently in Tiny model than in other models, so
  259. ; we need to ensure that __TINY__ is defined in tiny model.
  260. ;
  261. IFDEF @Model        ; simplified memory models being used?
  262.   IF @Model eq 1    ; tiny model
  263.      IFNDEF __TINY__
  264.        __TINY__ equ 1
  265.      ENDIF ;NDEF
  266.   ENDIF
  267.   IF (@Model eq 1) or (@Model eq 2) or (@Model eq 3) ; Tiny, Small, or Compact?
  268.      DIST equ NEAR
  269.   ELSE
  270.      DIST equ FAR
  271.   ENDIF
  272. ELSE ;DEF @Model    ; else assume TCC/BCC memory-model #defines
  273.    IFDEF __TINY__
  274.       DIST equ NEAR
  275.    ELSEIFDEF __SMALL__
  276.       DIST equ NEAR
  277.    ELSEIFDEF __COMPACT__
  278.       DIST equ NEAR
  279.    ELSE
  280.       DIST equ FAR
  281.    ENDIF
  282. ENDIF
  283.  
  284. IFNDEF __TINY__
  285.    TGROUP@ equ TGROUP
  286. ENDIF
  287.  
  288. ;-----------------------------------------------------------------------
  289. ;
  290. ; first half of startup code (invoke right after INCLUDE AMIS.MAC in main module)
  291. ;
  292. ; arguments:    major,minor,stksize
  293. ;        [opt] major,minor   major/minor version of min supported DOS ver
  294. ;        [opt] stksize        size of initial stack for non-Tiny models
  295. ;
  296. @Startup MACRO major,minor,stksize
  297.   ;----------------------------------
  298.   ; Declare our segments in the order
  299.   ; we want them in the executable.
  300.   ;
  301.   _INIT    SEGMENT PUBLIC PARA 'INIT'
  302.   _INIT    ENDS
  303.   TSRgroup@
  304.   _TEXT    SEGMENT PUBLIC PARA 'CODE' ; must be aligned PARA to work properly
  305.   _TEXT    ENDS
  306. IFNDEF __TINY__
  307.   _STACK SEGMENT STACK 'STACK'
  308.   IFNB <stksize>
  309.       db <stksize> dup (?)
  310.   ELSE
  311.         db 100h dup (?)
  312.   ENDIF
  313.   _STACK ENDS
  314. ENDIF ;ndef __TINY__
  315.  
  316.   ;----------------------------------
  317.   ; set up labels for start and end of
  318.   ; resident code
  319.   ;
  320.   TSRcode@
  321.   $AMIS$start_TSRcode label byte    ; find address of beginning of segment
  322.   TSRcodeEnd@
  323.  
  324.   TSRlast@
  325.   $AMIS$end_TSRcode label byte    ; marker for end of resident code in executable
  326.   TSRlastEnd@
  327.  
  328. IFDEF __TINY__
  329. _INIT SEGMENT 'INIT'
  330.     ASSUME    CS:_INIT,DS:_INIT,ES:_INIT,SS:_INIT
  331.     ORG    100h
  332. ELSE
  333. _TEXT SEGMENT 'CODE'
  334.     ASSUME    CS:_TEXT,DS:NOTHING,ES:NOTHING,SS:NOTHING
  335. ENDIF ;def __TINY__
  336.  
  337. INIT    proc far
  338. IFNB <major>
  339.   IFNB <minor>
  340.       CHECK_DOS_VER major,minor
  341.   ENDIF
  342. ENDIF
  343. IFNDEF __TINY__
  344.     mov    dx,TGROUP
  345.     mov    es,dx
  346.     ASSUME    ES:TGROUP
  347.     jmp    $AMIS$PROGRAM_START
  348. ELSE
  349.     mov    ax,offset _INIT:$AMIS$start_TSRcode
  350.     mov    cl,4
  351.     shr    ax,cl
  352.     mov    dx,es
  353.     add    dx,ax
  354.     mov    es,dx
  355.     ASSUME    ES:TGROUP
  356.     ;
  357.     ; compute normalized address of actual program entry point
  358.     ;
  359.     mov    dx,offset _INIT:$AMIS$PROGRAM_START
  360.     mov    ax,offset _TEXT:$AMIS$PROGRAM_START
  361.     sub    dx,ax
  362.     shr    dx,cl            ; CL still 4
  363.     mov    cx,cs
  364.     add    dx,cx
  365.     push    dx            ; simulate far jump to computed address
  366.     push    ax
  367.     ret
  368. ENDIF ;ndef __TINY__
  369.  
  370. INIT    endp
  371.  
  372.     ASSUME    DS:NOTHING,ES:NOTHING,SS:NOTHING
  373. IFDEF __TINY__
  374.  _INIT    ENDS
  375. ELSE
  376.  _TEXT    ENDS
  377. ENDIF ;def __TINY__
  378.  
  379.     ENDM
  380.  
  381. ;-----------------------------------------------------------------------
  382. ;
  383. ; additional startup code (invoke at start of main program)
  384. ;
  385. ; arguments: need_psp    non-blank to allocate __psp variable, blank if provided
  386. ;            by some other module (such as the C runtime library)
  387. ;
  388. @Startup2 MACRO need_psp
  389.  
  390. IFDEF __TINY__
  391.   TGROUP@    dw ?
  392. ENDIF ;__TINY__
  393. IFNB <need_psp>
  394.   public __psp
  395.   __psp        dw ?
  396. ENDIF ;need_psp
  397.  
  398. $AMIS$PROGRAM_START:
  399.     ASSUME    DS:NOTHING,ES:TGROUP
  400.     mov    __psp,ds
  401. IFDEF __TINY__
  402.     mov    TGROUP@,es
  403. ENDIF
  404.     ENDM
  405.  
  406. ;-----------------------------------------------------------------------
  407. ;
  408. ; installation flags (mainly internal use--see INSTALL_TSR below)
  409. ;
  410. BEST_FIT   equ 1    ; use best-fit rather than first-fit
  411. UMB_ONLY   equ 2    ; don't load into low memory, only into a UMB
  412. LOW_ONLY   equ 4    ; don't use UMB even if high memory available
  413.             ; (note: can't set both UMB_ONLY and LOW_ONLY)
  414. USE_TOPMEM equ 8    ; use the top of low memory if no high memory
  415.             ; (this is not always the best place to load)
  416. PATCH_RESIDENT equ 80h  ; patch resident code with actual memory block address
  417.  
  418. ;-----------------------------------------------------------------------
  419. ;
  420. ; DISPLAY_STRING    output a '$'-terminated string to standard output
  421. ; arguments:    string    the label of the string to be displayed
  422. ;        dataseg [opt] the segment of the string
  423. ;
  424. DISPLAY_STRING MACRO string,dataseg
  425. IFNB <dataseg>
  426.     push    ds
  427.     mov    ax,dataseg
  428.     mov    ds,ax
  429. ENDIF
  430.     mov    dx,offset string
  431.     mov    ah,9
  432.     int    21h
  433. IFNB <dataseg>
  434.     pop    ds
  435. ENDIF
  436.     ENDM
  437.  
  438. ;-----------------------------------------------------------------------
  439. ;
  440. ; CHECK_DOS_VER        ensure that the program is running under the proper
  441. ;            version of DOS, and terminate with an error message
  442. ;            specifying the minimum required version if not.
  443. ;
  444. CHECK_DOS_VER MACRO major,minor
  445.     LOCAL    bad_version_msg,version_OK
  446. IF major GE 5
  447.     mov    ax,3306h        ; get true DOS version
  448. ELSE
  449.     mov    ax,3000h
  450. ENDIF
  451.     int    21h
  452.     xchg    al,ah
  453.     cmp    ax,256*major + minor
  454.     jae    version_OK
  455. IFNDEF __TINY__
  456.     push    cs
  457.     pop    ds
  458. ENDIF
  459.     DISPLAY_STRING bad_version_msg
  460.     int    20h            ; terminate program
  461.  
  462. bad_version_msg label byte
  463.     db    "This program requires DOS "
  464.     db    major+'0',".",(minor/10)+'0',(minor mod 10)+'0'
  465.     db    " or higher.",13,10,"$"
  466.  
  467. version_OK:
  468.     ENDM
  469.  
  470. ;-----------------------------------------------------------------------
  471. ;
  472. ; IF_INSTALLED    conditionally branch somewhere if TSR is already installed
  473. ; arguments:
  474. ;    dest    label to branch to if already installed
  475. ; at exit:
  476. ;    CF set if installed
  477. ;        AH = multiplex number
  478. ;        CX = version number
  479. ;    CF clear if not installed
  480. ;
  481. IF_INSTALLED MACRO dest
  482.     LOCAL    not_installed
  483.     mov    dx,TGROUP@
  484.     mov    ax,offset RESIDENT_CODE:ALTMPX_SIGNATURE
  485.     extrn check_if_installed:DIST
  486.     call    check_if_installed
  487.     jnc    not_installed
  488.     jmp    dest
  489. not_installed:
  490.     ENDM
  491.  
  492. ;-----------------------------------------------------------------------
  493. ;
  494. ; IF_HOTKEY_USED conditionally branch somewhere if TSR's hotkeys already in use
  495. ; arguments:
  496. ;    dest    label to branch to if one or more hotkeys conflict
  497. ; at exit:
  498. ;    ZF clear if hotkeys conflict
  499. ;        AX = conflict types
  500. ;        bit 0: exact key already in use
  501. ;        bit 1: key with less-strict shift states in use
  502. ;        bit 2: key with stricter shift states in use
  503. ;    ZF set if no conflicts
  504. ;
  505. IF_HOTKEY_USED MACRO dest
  506.     LOCAL    no_conflicts
  507.     mov    dx,TGROUP@
  508.     mov    ax,offset TGROUP:$AMIS$HOTKEY_LIST
  509.     extrn check_if_hotkeys_used:DIST
  510.     call    check_if_hotkeys_used
  511.     jz    no_conflicts
  512.     jmp    dest
  513. no_conflicts:
  514.     ENDM
  515.  
  516. ;-----------------------------------------------------------------------
  517. ;
  518. ; INSTALL_TSR
  519. ; arguments:
  520. ;    extra    [opt] number of additional paragraphs needed in resident part
  521. ;    fit    [opt] FIRST (default) or BEST fit allocation
  522. ;    high    [opt] HIGHONLY to only use UMBs, TOPMEM to allocate block at
  523. ;            high end of conventional memory if no UMBs available,
  524. ;            LOWONLY to ignore UMBs, and TOPLOW to allocate at high
  525. ;            end of conventional memory whether or not UMBs are
  526. ;            available
  527. ;    init    [opt] function to call after installing TSR but before exiting
  528. ;    if_inst [opt] label to branch to if already installed
  529. ;    on_err    [opt] label to branch to if unable to install
  530. ;    more_flags [opt] label of byte containing additional flags to OR into
  531. ;           flags setup by <fit> and <high>
  532. ;
  533. ; if 'init' is specified, the indicated function will be called with
  534. ;    AX = segment at which TSR was loaded
  535. ; if 'if_inst' is specified, the indicated function will be jumped at with
  536. ;    AH = multiplex number
  537. ;    CX = version number
  538. ;
  539. INSTALL_TSR MACRO extra,fit,high,init,if_inst,on_err,more_flags
  540.     LOCAL not_installed,install_failed,iflags
  541.     mov    bx,TGROUP@
  542.     push    bx            ; remember location of resident code
  543.     mov    dx,bx
  544.     mov    ax,offset RESIDENT_CODE:ALTMPX_SIGNATURE
  545.     extrn    check_if_installed:DIST
  546.     call    check_if_installed
  547.     pop    bx            ; retrieve location of resident code
  548.     jnc    not_installed
  549. install_failure:
  550. IFNB <if_inst>
  551.     jmp    if_inst
  552. ELSE
  553.     jmp short install_failed
  554. ENDIF
  555. not_installed:
  556.     cmp    al,1
  557.     je    install_failure
  558.     mov    dx,offset TGROUP:$AMIS$end_TSRcode+15
  559.     mov    cl,4            ; convert bytes to paragraphs
  560.     shr    dx,cl
  561.     mov    cx,dx
  562. IFNB <extra>
  563.     mov    dx,extra
  564. ELSE
  565.     xor    dx,dx            ; no extra memory required
  566. ENDIF
  567.     iflags = 0
  568. IFDIFI <fit>,<FIRST>
  569.     iflags = iflags OR BEST_FIT
  570. ENDIF
  571. IFIDNI <high>,<HIGHONLY>
  572.     iflags = iflags OR UMB_ONLY
  573. ENDIF
  574. IFIDNI <high>,<LOWONLY>
  575.     iflags = iflags OR LOW_ONLY
  576. ENDIF
  577. IFIDNI <high>,<TOPMEM>
  578.     iflags = iflags OR USE_TOPMEM
  579. ENDIF
  580. IFIDNI <high>,<TOPLOW>
  581.     iflags = iflags OR USE_TOPMEM OR LOW_ONLY
  582. ENDIF
  583. IFDEF ALTMPX$PSP
  584.     iflags = iflags OR PATCH_RESIDENT
  585. ENDIF
  586.     mov    al,iflags
  587. IFNB <more_flags>
  588.     or    al,more_flags
  589. ENDIF
  590.     extrn $install_TSR:DIST
  591.     call    $install_TSR
  592.     ; if success, returns CF clear, AX=segment at which TSR was installed
  593.     jc    install_failed
  594. IFNB <&init>
  595.     call    init
  596. ENDIF
  597.     extrn $go_TSR:DIST
  598.     call    $go_TSR            ; never returns
  599.  
  600. install_failed:
  601. IFNB <on_err>
  602.     jmp    on_err
  603. ELSE
  604.     push    cs
  605.     pop    ds
  606.     DISPLAY_STRING cs:install_error_msg
  607.     mov    ax,4CFFh        ; exit with ERRORLEVEL 255
  608.     int    21h
  609.  
  610. install_error_msg db "Unable to go resident.",13,10,"$"
  611. ENDIF
  612.     ENDM
  613.  
  614.  
  615. ;-----------------------------------------------------------------------
  616. ;
  617. ; UNINSTALL    remove the TSR from memory
  618. ; arguments:
  619. ;    on_err    [opt] label to branch to if unable to remove from memory
  620. ;
  621. ; If 'on_err' is omitted, check CF after this macro to determine whether
  622. ; the removal was successful (CF clear if successful, set on error)
  623. ;
  624. UNINSTALL MACRO on_err
  625.     LOCAL    success
  626.     mov    dx,TGROUP@
  627.     mov    ax,offset RESIDENT_CODE:ALTMPX_SIGNATURE
  628.     extrn $uninstall_TSR:DIST
  629.     call    $uninstall_TSR
  630. IFNB <on_err>
  631.     jnc    success
  632.     jmp    on_err
  633. ENDIF
  634. success:
  635.     ENDM
  636.  
  637. ;-----------------------------------------------------------------------
  638. ;
  639. ;             I M P O R T A N T ! ! !
  640. ; Note: in order to work properly with the code in ALTMPX.ASM, all of
  641. ; the following macros must be used inside TSRcode@
  642. ;
  643.  
  644. ;-----------------------------------------------------------------------
  645. ;
  646. ; ISP_HEADER    set up Interrupt Sharing Protocol header for an interrupt
  647. ; arguments:
  648. ;    intr    interrupt number
  649. ;    reset    [opt] name of routine to perform hardware reset
  650. ;    eoi    [opt] if nonzero, this is the primary handler for a hardware int
  651. ; exported labels: (for example "ISP_HEADER 00h,reset_func,0")
  652. ;    INT00h_handler (public), ORIG_INT00h (public), HWRESET_00h,
  653. ;    EOI_FLAG_00h
  654. ;    [in addition, hw_reset_00h would be present for ISP_HEADER 00h,,0]
  655. ;
  656. ISP_HEADER MACRO intr,reset,eoi
  657. public INT&intr&_handler,ORIG_INT&intr
  658.     ASSUME    DS:NOTHING,ES:NOTHING,SS:NOTHING
  659. IFB <reset>
  660. hw_reset_&intr:
  661.     db    0CBh            ; RETF
  662. ENDIF ;reset
  663.  
  664. INT&intr&_handler:
  665.     db    0EBh,10h        ; short JMP to skip the header
  666. ORIG_INT&intr dd ?            ; previous handler in chain
  667.     dw   424Bh            ; ISP signature
  668. EOI_FLAG_&intr label byte
  669. IFB <eoi>
  670.     db   0                ; software int or secondary hardware int
  671. ELSE
  672. IF eoi eq 0
  673.     db   0                ; software int or secondary hardware int
  674. ELSE
  675.     db   80h            ; primary hardware int handler
  676. ENDIF ;eoi eq 0
  677. ENDIF ;B eoi
  678. IFB <reset>
  679. HWRESET_&intr: jmp short hw_reset_&intr
  680. ELSE
  681. HWRESET_&intr: jmp short reset
  682. ENDIF ;B reset
  683.     db   7 dup (0)
  684.     ENDM
  685.  
  686. ;-----------------------------------------------------------------------
  687. ;
  688. ; HOOKED_INTS        declare the interrupts this TSR hooks
  689. ; arguments:        up to 32 interrupt numbers
  690. ; exported labels:    $AMIS$HOOKED_INT_LIST (public)
  691. ;
  692. HOOKED_INTS MACRO a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,aa,ab,ac,ad,ae,af,over
  693. public $AMIS$HOOKED_INT_LIST
  694. $AMIS$HOOKED_INT_LIST label byte
  695. IFNB <over>
  696.     %out Too many interrupts hooked!
  697.     .err
  698. ENDIF ;NB over
  699.     IRP    intrpt,<a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,aa,ab,ac,ad,ae,af>
  700.         IFNB <intrpt>
  701.         IF intrpt ne 2Dh   ; ignore INT 2Dh if in the list
  702.             DB 0&&intrpt
  703.             DW INT&&intrpt&&_handler
  704.         ENDIF ;DIFI
  705.         ENDIF ;NB
  706.     ENDM
  707.     ;
  708.     ; the list terminator is INT 2Dh, since we know that one will always
  709.     ; be hooked; thus, all interrupts from 00h to FFh may be hooked
  710.     ;
  711.             DB 2Dh
  712.             DW INT2Dh_handler
  713.     ENDM
  714.  
  715. ;-----------------------------------------------------------------------
  716. ;
  717. ; HOTKEYS        declare the type of hotkeys this TSR uses
  718. ; arguments:
  719. ;    check    hotkey check type
  720. ;    flags    [opt] default flags for following hotkeys
  721. ; exported labels:    $AMIS$HOTKEY_LIST (public),
  722. ;            $amis$hotkey_list_start (internal use)
  723. ;
  724. ; To declare the TSR's hotkeys, you must use macros in the following order:
  725. ;            HOTKEYS    type
  726. ;            HOTKEY    scan1,req1,disall1
  727. ;            HOTKEY    scan2,req2,disall2,flags2
  728. ;            ...
  729. ;            HOTKEY    scanN,reqN,disallN
  730. ;            HOTKEYS_DONE
  731. ; these definitions must precede the use of the ALTMPX macro
  732. ;
  733. HOTKEYS MACRO check,flags
  734. public $AMIS$HOTKEY_LIST
  735. $AMIS$HOTKEY_LIST label byte
  736.     db    check            ; type of hotkey check
  737.     db    $amis$num_hotkeys    ; number of hotkeys following
  738. $amis$hotkey_list_start label byte
  739. IFNB <flags>
  740.    $amis$hotkey_def_flags equ flags
  741. ELSE
  742.    IF (check AND HK_INT15EXIT)
  743.       $amis$hotkey_def_flags equ HK_CHAINBEFORE
  744.    ELSEIF (check AND HK_INT09EXIT)
  745.       $amis$hotkey_def_flags equ HK_CHAINBEFORE
  746.    ELSE
  747.       $amis$hotkey_def_flags equ HK_NOCHAIN
  748.    ENDIF
  749. ENDIF ;flags
  750.     ENDM
  751.  
  752. ;-----------------------------------------------------------------------
  753. ;
  754. ; HOTKEY        declare one of the hotkeys this TSR uses
  755. ; arguments:
  756. ;    scan    scan code
  757. ;    req    required shift states
  758. ;    disall    disallowed shift states
  759. ;    flags    [opt] flags describing actions taken on hotkey
  760. ; exported labels: none
  761. ;
  762. ; To declare the TSR's hotkeys, you must use macros in the following order:
  763. ;            HOTKEYS    type
  764. ;            HOTKEY    scan1,req1,disall1
  765. ;            HOTKEY    scan2,req2,disall2,flags2
  766. ;            ...
  767. ;            HOTKEY    scanN,reqN,disallN
  768. ;            HOTKEYS_DONE
  769. ; these definitions must precede the use of the ALTMPX macro; the first HOTKEY
  770. ; line should define the TSR's primary hotkey
  771. ;
  772. HOTKEY    MACRO    scan,req,disall,flags
  773.     LOCAL    t
  774.     db    scan
  775. IFNB <req>
  776.     dw    req
  777. ELSE
  778.     dw    HK_NONE
  779. ENDIF ;req
  780. IFNB <disall>
  781.     t = disall
  782.    IF (((disall) AND HK_ANYSHIFT) eq HK_ANYSHIFT)
  783.        t = t OR HK_LSHIFT OR HK_RSHIFT
  784.    ENDIF
  785.    IF (((disall) AND HK_ANYCTRL) eq HK_ANYCTRL)
  786.        t = t OR HK_LCTRL OR HK_RCTRL
  787.    ENDIF
  788.    IF (((disall) AND HK_ANYALT) eq HK_ANYALT)
  789.        t = t OR HK_LALT OR HK_RALT
  790.    ENDIF
  791.     dw    t
  792. ELSE
  793.     dw    HK_NONE
  794. ENDIF ;disall
  795. IFNB <flags>
  796.     db    flags
  797. ELSE
  798.     db    $amis$hotkey_def_flags
  799. ENDIF ;flags
  800.     ENDM
  801.  
  802. ;-----------------------------------------------------------------------
  803. ;
  804. ; HOTKEYS_DONE        mark end of hotkey list
  805. ; arguments:    none
  806. ; exported labels:    $amis$num_hotkeys (equate)
  807. ;
  808. ; To declare the TSR's hotkeys, you must use macros in the following order:
  809. ;            HOTKEYS    type
  810. ;            HOTKEY    scan1,req1,disall1
  811. ;            HOTKEY    scan2,req2,disall2
  812. ;            ...
  813. ;            HOTKEY    scanN,reqN,disallN
  814. ;            HOTKEYS_DONE
  815. ; these definitions must precede the use of the ALTMPX macro
  816. ;
  817. HOTKEYS_DONE MACRO
  818. $amis$num_hotkeys equ ($-$amis$hotkey_list_start)/6
  819.     ENDM
  820.  
  821. ;-----------------------------------------------------------------------
  822. ;
  823. ; ALTMPX    define the alternate multiplex interrupt handler for the program
  824. ; arguments:
  825. ;    manuf       one- to eight-character manufacturer's name
  826. ;    prodname   one- to eight-character product name
  827. ;    version       four-digit hex version number (hi byte = major, lo = minor)
  828. ;    descrip       [opt] string (max 63 char) describing the product
  829. ;    priv_funcs [opt] name of routine to handle private INT 2Dh functions
  830. ;    api_entry  [opt] name of FAR routine giving non-INT 2Dh API entry point
  831. ;    popup       [opt] name of function to call to request a popup
  832. ;    remover       [opt] name of function to call to remove TSR from memory
  833. ;    psp       [opt] if nonblank, set up patch word for memblk segment to
  834. ;             be returned if <remover> omitted; returns CS if both
  835. ;             <remover> and <psp> blank
  836. ; limitations on routines:
  837. ;    all: must be located inside TSRcode@
  838. ;    <priv_funcs>
  839. ;        input:    AL = function number (10h-FFh)
  840. ;            AH = multiplex number (ignore)
  841. ;            others available for handler
  842. ;        return: via IRET, with regs as appropriate for requested func
  843. ;    <api_entry>
  844. ;        input:    registers as desired (no limitations)
  845. ;        return: registers as desired (no limitations)
  846. ;    <popup>
  847. ;        input:    nothing
  848. ;        return: AL = status
  849. ;                01h can not pop up now, try again later
  850. ;                02h can not pop up yet, will do so when able
  851. ;                03h already popped up
  852. ;                04h unable to popup, user intervention required
  853. ;                    BX = standard reason code
  854. ;                    0000h unknown failure
  855. ;                    0001h int chain passes through memory
  856. ;                        which must be swapped out
  857. ;                    0002h swap-in failed
  858. ;                    CX = application's reason code if nonzero
  859. ;                FFh TSR popped up and was exited by user
  860. ;                    BX = return value
  861. ;                    0000h no return value
  862. ;                    0001h TSR unloaded
  863. ;                    0002h-00FFh reserved
  864. ;                    0100h-FFFFh application-specific
  865. ;    <remover>
  866. ;        input:    DX:BX = return address if uninstall successful
  867. ;        return: AL = status
  868. ;                01h unable to remove from memory
  869. ;                02h can't remove now, will do so when able
  870. ;                03h safe to remove, but no resident uninstaller
  871. ;                    (TSR still enabled)
  872. ;                    BX = segment of memory block
  873. ;                04h safe to remove, but no resident uninstaller
  874. ;                    (TSR now disabled)
  875. ;                    BX = segment of memory block
  876. ;                05h not safe to remove now, try again later
  877. ;                FFh successful (DX:BX were ignored)
  878. ;        return at DX:BX with AX destroyed if successful and <remover>
  879. ;            honors specific return address
  880. ;        if <remover> omitted, ALTMPX returns AL=03h
  881. ; exported labels:
  882. ;    INT2Dh_handler (public), ORIG_INT2Dh (public), HWRESET_2Dh,
  883. ;    EOI_FLAG_2Dh, hw_reset_2Dh, $AMIS$MULTIPLEX_NUMBER (public),
  884. ;    ALTMPX_SIGNATURE (public), ALTMPX$PSP [patch word]
  885. ;
  886. ALTMPX MACRO manuf,prodname,version,descrip,priv_funcs,api_entry,popup,remover,psp
  887.     LOCAL our_int_2Dh,int2D_func_00,int2D_func_01,int2D_func_02
  888.     LOCAL int2D_func_03,int2D_func_04
  889.     LOCAL func_is_supported,func_not_supported,func_supported_segDX
  890.     PUBLIC $AMIS$MULTIPLEX_NUMBER,ALTMPX_SIGNATURE,ALTMPX$PSP
  891.  
  892. ALTMPX_SIGNATURE label byte
  893.     db    manuf
  894. IF ($-ALTMPX_SIGNATURE) gt 8
  895.     ERR "Manufacturer name >8 chars"
  896. ELSEIF ($-ALTMPX_SIGNATURE) lt 8
  897.     db    (ALTMPX_SIGNATURE+8-$) dup (' ')
  898. ENDIF
  899.     db    prodname
  900. IF ($-ALTMPX_SIGNATURE) gt 16
  901.     ERR "Product name >8 chars"
  902. ELSEIF ($-ALTMPX_SIGNATURE) lt 16
  903.     db    (ALTMPX_SIGNATURE+16-$) dup (' ')
  904. ENDIF
  905. IFNB <descrip>
  906.     db    descrip
  907. ENDIF
  908.     db    0
  909. IF ($-ALTMPX_SIGNATURE) gt 80
  910.     ERR "Description >63 chars"
  911. ENDIF
  912.  
  913. ; save an additional byte by overlaying the null hardware reset handler over
  914. ; other code, if possible
  915. IFNB <remover>
  916. hw_reset_2Dh:                ; <remover> not blank
  917.     db    0CBh            ; RETF
  918. IFNDEF ALTMPX$PSP
  919. ALTMPX$PSP equ word ptr ($+12)        ; point harmlessly into the ISP header
  920. ENDIF
  921. ELSE
  922.    IFB <psp>
  923.       ALTMPX$PSP equ word ptr ($+12)    ; point harmlessly into the ISP header
  924.    ENDIF
  925. ENDIF
  926. IFNB <psp>
  927.    IFB <remover>
  928. hw_reset_2Dh:                ; <remover> blank but <psp> not
  929.     db    0CBh            ; RETF
  930.    ENDIF
  931. ENDIF
  932.                     ; if both <remover> and <psp> blank,
  933.                     ;   hw_reset_2Dh is defined below
  934.                     ; if <remover> is blank and <psp> not,
  935.                     ;   ALTMPX$PSP is defined below
  936.  
  937.     ISP_HEADER 2Dh,hw_reset_2Dh
  938.     cmp    ah,0            ; will be patched with multiplex number
  939. $AMIS$MULTIPLEX_NUMBER equ byte ptr ($-1)
  940.     je    our_int_2Dh
  941.     jmp    ORIG_INT2Dh
  942. our_int_2Dh:
  943.     sti                ; OK to interrupt from now on
  944.     cmp    al,0
  945.     je    int2D_func_00
  946.     cmp    al,2
  947. IFNB <api_entry>
  948.     jb    int2D_func_01
  949. ELSE
  950.   IFNB <popup>
  951.     jb    func_not_supported
  952.   ENDIF
  953. ENDIF
  954.     je    int2D_func_02
  955.     cmp    al,4
  956. IFNB <popup>
  957.     jb    int2D_func_03
  958. ENDIF ;popup
  959.     je    int2D_func_04
  960. IFDEF $amis$num_hotkeys
  961.     cmp    al,5
  962.     jne    not_hotkey_check
  963.     mov    bx,offset TGROUP:$AMIS$HOTKEY_LIST
  964.     jmp short func_supported_segDX
  965. not_hotkey_check:
  966. ENDIF ;$amis$num_hotkeys
  967. IFNB <priv_funcs>
  968.     cmp    al,10h
  969.     jb    func_not_supported
  970.         jmp     priv_funcs
  971. ENDIF ;priv_funcs
  972. func_not_supported:
  973.     mov    al,0
  974.     iret
  975.  
  976. int2D_func_00:
  977.     mov    cx,version
  978.     mov    di,offset ALTMPX_SIGNATURE
  979. func_supported_segDX:
  980.     mov    dx,cs
  981. func_is_supported:
  982.     mov    al,0FFh
  983.     iret
  984.  
  985. IFNB <api_entry>
  986. int2D_func_01:
  987.     mov    bx,offset api_entry
  988.     jmp    func_supported_segDX
  989. ENDIF ;api_entry
  990.  
  991. int2D_func_02:
  992. IFNB <remover>
  993.     call    remover
  994. ELSE
  995. ;    mov    al,3            ; safe to remove, no resident uninstaller
  996.     inc    ax            ; AL was 02h, now 03h
  997. IFNB <psp>
  998.     mov    bx,0            ; will be patched at installation time
  999. ALTMPX$PSP equ word ptr ($-2)
  1000. ELSE
  1001.     mov    bx,cs
  1002. hw_reset_2Dh equ near ptr ($-1) ; prev instruction happens to expand to 8Ch CBh
  1003. ENDIF ;psp
  1004. ENDIF ;remover
  1005.     iret
  1006.  
  1007. IFNB <popup>
  1008. int2D_func_03:
  1009.     call    popup
  1010.     iret
  1011. ENDIF ;popup
  1012.  
  1013. int2D_func_04:
  1014.     ;mov    al,4 ;not needed since AL=04h anyway
  1015.     mov    dx,cs
  1016.     mov    bx,offset cs:$AMIS$HOOKED_INT_LIST
  1017.     iret
  1018.  
  1019.     ENDM
  1020.  
  1021. ;-----------------------------------------------------------------------
  1022. ; generic hotkey dispatcher
  1023. ; args:
  1024. ;    chain    when to chain INT 15h: BEFORE or AFTER
  1025. ;        should match what HOTKEYS macro declares
  1026. ;    funcs    name of list of words containing offsets for the NEAR 
  1027. ;        functions to invoke for each hotkey (in the order they are
  1028. ;        listed via the HOTKEY macro)
  1029. ;    other    [opt] address to jump at if not INT 15/AH=4Fh
  1030. ;
  1031. HOTKEY_DISPATCHER MACRO chain,funcs,other
  1032.     LOCAL    int15_handler,not_anyshift
  1033.     LOCAL    int15_4F,int15_done,scan_hotkeys,try_next,not_hotkey
  1034.     LOCAL    got_hotkey,no_chainbefore,no_chainafter,chain_1
  1035.  
  1036. int15_handler proc far
  1037. ISP_HEADER 15h
  1038.     ASSUME    DS:NOTHING,ES:NOTHING,SS:NOTHING
  1039. IFIDNI <chain>,<BEFORE>
  1040.     pushf
  1041.     call    ORIG_INT15h
  1042. ENDIF ;chain
  1043.     cmp    ah,4Fh
  1044.     je    int15_4F
  1045. IFNB <other>
  1046.     jmp    other
  1047. ELSE
  1048.    IFIDNI <chain>,<BEFORE>
  1049.        iret                ; we've already chained
  1050.    ELSE
  1051. chain_1:
  1052.     jmp    ORIG_INT15h
  1053.    ENDIF ;chain
  1054. ENDIF ;other
  1055.  
  1056. int15_4F:
  1057.     sti                ; OK to interrupt
  1058.     cld                ; string ops move up in memory
  1059.     push    bx
  1060.     push    ax
  1061.     mov    ah,12h            ; get shift states
  1062.     int    16h
  1063.     and    ax,not HK_ANYSHIFT
  1064.     test    ax,HK_RSHIFT or HK_LSHIFT
  1065.     jz    not_anyshift
  1066.     or    ax,HK_ANYSHIFT
  1067. not_anyshift:
  1068.     mov    bx,ax            ; BX <- current shift states
  1069.     pop    ax            ; restore scan code in AL
  1070.     push    ds
  1071.     push    si
  1072.     push    cx
  1073.     push    cs
  1074.     pop    ds
  1075.     ASSUME    DS:TGROUP
  1076.     mov    si,offset TGROUP:$AMIS$HOTKEY_LIST+1
  1077.     mov    cl,[si]
  1078.     jcxz    not_hotkey        ; skip loop if no hotkeys active
  1079.     inc    si            ; skip hotkey list header
  1080. scan_hotkeys:
  1081.     cmp    al,[si]            ; is it our hotkey?
  1082.     jne    try_next        ; if scan code differs, it isn't
  1083.     test    bx,[si+3]        ; any disallowed shift states active?
  1084.     jnz    try_next        ; if yes, not our hotkey
  1085.     push    bx
  1086.     not    bx
  1087.     test    bx,[si+1]        ; any required shift states missing?
  1088.     pop    bx
  1089.     jz    got_hotkey
  1090. try_next:
  1091.     add    si,6            ; move to next hotkey record
  1092.     loop    scan_hotkeys
  1093. not_hotkey:
  1094.     stc                ; key not used by TSR
  1095.     pop    cx
  1096.     pop    si
  1097.     pop    ds
  1098.     ASSUME    DS:NOTHING
  1099.     pop    bx
  1100. IFDIFI <chain>,<BEFORE>
  1101.    IFNB <other>
  1102.        jmp    ORIG_INT15h
  1103.    ELSE
  1104.     jmp    chain_1
  1105.    ENDIF ;other
  1106. ELSE
  1107.     iret
  1108. ENDIF ;chain
  1109.  
  1110. got_hotkey:
  1111.     ASSUME    DS:TGROUP
  1112.     push    ax
  1113.     mov    ax,si
  1114.     sub    ax,offset TGROUP:$AMIS$HOTKEY_LIST+2
  1115.     mov    bl,3
  1116.     div    bl
  1117.     mov    bx,ax            ; BX <- offset of func in hk-func list
  1118.     pop    ax
  1119.     pop    cx
  1120. IFDIFI <chain>,<BEFORE>
  1121.     test    byte ptr [si+5],HK_CHAINBEFORE
  1122.     jz    no_chainbefore
  1123.     stc
  1124.     pushf
  1125.     call    ORIG_INT15h
  1126. no_chainbefore:
  1127.     test    byte ptr [si+5],HK_CHAINAFTER
  1128. ENDIF ;chain
  1129.     pop    si
  1130.     pop    ds
  1131.     ASSUME    DS:NOTHING
  1132. IFDIFI <chain>,<BEFORE>
  1133.     pushf
  1134. ENDIF ;chain
  1135.     call    word ptr RESIDENT_CODE:[bx+funcs]
  1136. IFDIFI <chain>,<BEFORE>
  1137.     popf
  1138.     pop    bx
  1139.   IFNB <other>
  1140.     jz    no_chainafter
  1141.     stc
  1142.     jmp    ORIG_INT15h
  1143.   ELSE
  1144.       stc
  1145.         jnz    chain_1
  1146.   ENDIF ;other
  1147. no_chainafter:
  1148. ELSE
  1149.     pop    bx
  1150. ENDIF ;chain
  1151.     clc                ; throw out scan code, all processing done
  1152.     ret    2
  1153. int15_handler endp
  1154.  
  1155.     ENDM
  1156.  
  1157. ;-----------------------------------------------------------------------
  1158. ;
  1159. TSRstack@ MACRO size
  1160. TSRbss@
  1161. TSR_local_stack db size dup (?)
  1162. TSR_local_stack_end label byte
  1163. TSRbssEnd@
  1164.     ENDM
  1165.  
  1166. ;-----------------------------------------------------------------------
  1167. ; high-level language interrupt handler interface for AMISLIB
  1168. ; not yet ready to use
  1169. ;
  1170. ;    chain    one of BEFORE, FIRST, DURING, AFTER, NONE
  1171. ;
  1172. AMIS_INT MACRO intnum,chain,dseg,localstk,handler,resetfunc,reg,val1,val2,val3,val4,val5,val6,val7,over
  1173.     LOCAL    TESTVALUES, our_func, not_ours, stackptr
  1174. TESTVALUES = 0
  1175.  
  1176. IFB <dseg>
  1177.     .err "Must specify DSEG"
  1178. ENDIF
  1179. IFB <handler>
  1180.     .err "Must specify an interrupt handler"
  1181. ENDIF
  1182. IFNB <over>
  1183.     .err "Too many values specified"
  1184. ENDIF
  1185.  
  1186. hw_reset_&intnum proc far
  1187.     ASSUME    DS:NOTHING,ES:NOTHING,SS:NOTHING
  1188. IFNB <resetfunc>
  1189.     pushf
  1190.     push    es
  1191.     push    ds
  1192.     push    bp
  1193.     push    di
  1194.     push    si
  1195.     push    dx
  1196.     push    cx
  1197.     push    bx
  1198.     push    ax
  1199.     mov    ax,dseg
  1200.     mov    ds,ax
  1201.     call    resetfunc
  1202.     pop    ax
  1203.     pop    bx
  1204.     pop    cx
  1205.     pop    dx
  1206.     pop    si
  1207.     pop    di
  1208.     pop    bp
  1209.     pop    ds
  1210.     pop    es
  1211.     popf
  1212. ENDIF ;NB resetfunc
  1213.     ret
  1214. hw_reset_&intnum endp
  1215.  
  1216.     ISP_HEADER intnum,hw_reset_&intnum
  1217. IFNB <reg>
  1218.     pushf
  1219.     IRP    val,<val1,val2,val3,val4,val5,val6,val7>
  1220.         IFNB <val>
  1221.             cmp    reg,val
  1222.         je    our_func
  1223.         TESTVALUES = 1
  1224.         ENDIF
  1225.     ENDM
  1226.     IF TESTVALUES
  1227.         popf
  1228.         jmp    orig_INT&intnum
  1229.     ENDIF
  1230. ENDIF
  1231.  
  1232. our_func:
  1233. IFIDNI <chain>,<BEFORE>
  1234.     call    orig_INT&intnum           ; chain, original flags already on stack
  1235. ELSE
  1236.     popf                ; clean up stack
  1237. ENDIF
  1238. IFNB <localstk>
  1239.  
  1240. ENDIF ;NB localstk
  1241. IFIDNI <chain>,<DURING>
  1242.     push    cs:stackptr
  1243. ENDIF
  1244.     pushf
  1245.     push    es
  1246.     push    ds
  1247.     push    bp
  1248.     push    di
  1249.     push    si
  1250.     push    dx
  1251.     push    cx
  1252.     push    bx
  1253.     push    ax
  1254. IFIDNI <chain>,<DURING>
  1255.     mov    cs:stackptr,sp
  1256. ENDIF
  1257.     mov    ax,dseg
  1258.     mov    ds,ax
  1259. IFIDNI <chain>,<FIRST>
  1260.     pushf
  1261.     call    orig_INT&intnum
  1262. ENDIF
  1263.     call    handler
  1264.     pop    ax
  1265.     pop    bx
  1266.     pop    cx
  1267.     pop    dx
  1268.     pop    si
  1269.     pop    di
  1270.     pop    bp
  1271.     pop    ds
  1272.     pop    es
  1273.     popf
  1274. IFIDINI <chain>,<DURING>
  1275.     pop    cs:stackptr
  1276. ENDIF
  1277. IFNB <localstk>
  1278.  
  1279. ENDIF ;NB localstk
  1280. IFIDNI <chain>,<AFTER>
  1281.     jmp    orig_INT&intnum
  1282. ELSE
  1283.     iret
  1284. ENDIF
  1285.  
  1286. IFIDNI <chain>,<DURING>
  1287. stackptr dw ?
  1288.  
  1289. public _chain_INT&intnum
  1290. _chain_INT&intnum proc dist
  1291.     ASSUME    DS:NOTHING,ES:NOTHING,SS:NOTHING
  1292.     push    bp
  1293.     mov    bp,stackptr
  1294.     mov    ax,[bp]
  1295.     mov    bx,[bp+2]
  1296.     mov    cx,[bp+4]
  1297.     mov    dx,[bp+6]
  1298.     mov    si,[bp+8]
  1299.     mov    di,[bp+0Ah]
  1300.     mov    ds,[bp+0Eh]
  1301.     mov    es,[bp+10h]
  1302.     push    word ptr [bp+12h]    ; push flags
  1303.     popf
  1304.     mov    bp,[bp+0Ch]
  1305.     pushf
  1306.     call    orig_INT&intnum        ; chain by simulating the interrupt
  1307.     push    bp
  1308.     mov    bp,stackptr
  1309.     pushf
  1310.     pop    word ptr [bp+12h]    ; store returned flags
  1311.     pop    word ptr [bp+0Ch]    ; store returned BP
  1312.     mov    [bp],ax
  1313.     mov    [bp+2],bx
  1314.     mov    [bp+4],cx
  1315.     mov    [bp+6],dx
  1316.     mov    [bp+8],si
  1317.     mov    [bp+0Ah],di
  1318.     mov    [bp+0Eh],ds
  1319.     mov    [bp+10h],es
  1320.     pop    bp
  1321.     ret
  1322. _chain_INT&intnum endp
  1323.     ENDM
  1324.  
  1325. ;-----------------------------------------------------------------------
  1326. ;
  1327. GRAB_INTERRUPT MACRO intnum,handler
  1328.     TSRbss@
  1329.     TSR_old_INT&intnum dd ?
  1330.     TSRbssEnd@
  1331.  
  1332.     mov    ax,3500h+intnum
  1333.     int    21h
  1334.     mov    word ptr TSR_old_INT&intnum,bx
  1335.     mov    word ptr TSR_old_INT&intnum+2,es
  1336.     mov    dx,offset TGROUP:handler
  1337.     mov    ax,2500h+intnum
  1338.     int    21h
  1339.     ENDM
  1340.  
  1341. ;-----------------------------------------------------------------------
  1342. ;
  1343. RESTORE_INTERRUPT MACRO intnum
  1344.     push    ds
  1345.     lds    dx,TSR_old_INT&intnum
  1346.     mov    ax,2500h+intnum
  1347.     int    21h
  1348.     pop    ds
  1349.     ENDM
  1350.  
  1351. ;-----------------------------------------------------------------------
  1352.  
  1353. .LIST
  1354.